`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/22 20:21:07
// Design Name: 
// Module Name: rv_all
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

`include "msg_config.v"
`include "rv_config.v"
module rv_all(
    input CLK,input RST,
    //Supervior --> rv_all
    input EBUS_SEL,
    input EBUS_DMEM_CS,
    input EBUS_IMEM_CS,
    input EBUS_WR,
    input [`EBUS_ADDR_WIDTH-1:0] EBUS_ADDR,
    input [127:0] EBUS_DIN,
    // 1:running 0:CLR
    input EBUS_RV_RUN,

    output [31:0] RV_FLAG
    );
    //thread_id and thread_id_valid----------
    //Generated by rv_thread module
    wire if_thread_id_valid;
    wire issue_thread_id_valid;
    wire decode_thread_id_valid;
    //thread_id_valid chain
    regw #(.WIDTH(1)) DECODE_THREAD_ID_VALID_REG(CLK,RST,1'b1,
      issue_thread_id_valid,decode_thread_id_valid);
    
    wire [1:0] if_thread_id;
    wire [1:0] issue_thread_id;
    wire [1:0] decode_thread_id;
    wire [1:0] ex_thread_id;
    wire [1:0] mem_thread_id;
    wire [1:0] wb_thread_id;
    //thread_id chain
    regw #(.WIDTH(2)) DECODE_THREAD_ID_REG(CLK,RST,1'b1,issue_thread_id,decode_thread_id);
    regw #(.WIDTH(2)) EX_THREAD_ID_REG(CLK,RST,1'b1,decode_thread_id,ex_thread_id);
    regw #(.WIDTH(2)) MEM_THREAD_ID_REG(CLK,RST,1'b1,ex_thread_id,mem_thread_id);
    regw #(.WIDTH(2)) WB_THREAD_ID_REG(CLK,RST,1'b1,mem_thread_id,wb_thread_id);

    //PC if_pc is generated by RV_PC module----------
    wire [31:0] if_pc,issue_pc,decode_pc,ex_pc;
    //PC chain
    regw #(.WIDTH(32)) ISSUE_PC_REG(CLK,RST,1'b1,if_pc,issue_pc);
    regw #(.WIDTH(32)) DECODE_PC_REG(CLK,RST,1'b1,issue_pc,decode_pc);
    regw #(.WIDTH(32)) EX_PC_REG(CLK,RST,1'b1,decode_pc,ex_pc);

    //rd index and rd_src: ex_rd_XXX is generated by rv_decode
    wire [4:0] ex_rd_index,mem_rd_index,wb_rd_index;
    wire [1:0] ex_rd_src,mem_rd_src;
    //rd_index chain
    regw #(.WIDTH(5)) MEM_RD_INDEX_REG(CLK,RST,1'b1,ex_rd_index,mem_rd_index);
    regw #(.WIDTH(5)) WB_RD_INDEX_REG(CLK,RST,1'b1,mem_rd_index,wb_rd_index);
    //rd_src chain
    regw #(.WIDTH(2)) MEM_RD_SRC_REG(CLK,RST,1'b1,ex_rd_src,mem_rd_src);

    //inst0 from IMEM
    //inst is set to NOP if the issue_thread_id_valid is 0
    //ir is the Instruction Register for decoder 
    wire [31:0] inst0,inst;
    wire [31:0] ir;

    rv_imem #(.addr_width (11))RV_IMEM (
      .CLK (CLK),
      .RST (RST),
      .EBUS_SEL (EBUS_SEL),
      .PC (if_pc),
      .CS_EBUS (EBUS_IMEM_CS),
      .WR_EBUS (EBUS_WR),
      .ADDR_EBUS (EBUS_ADDR),
      .DIN_EBUS (EBUS_DIN),
      .DOUT  (inst0)
    );

    //If non thread, then inst=NOP(ADDI x0,x0,0)
    assign inst=(issue_thread_id_valid==1)?inst0:{11'b0,5'b0,3'b0,5'b0,7'b0010011};
    regw #(.WIDTH(32)) IR(CLK,RST,1'b1,inst,ir);
    


    //update_pc is for target PC in JAL or Branch instructions
    //If update_pc_valid ==1 then the PC of the ex_thead_id is changed to update_pc 
    wire [31:0] update_pc;
    wire update_pc_valid;
    rv_pc RV_PC(
        .CLK (CLK),
        .RST (RST),
        .EBUS_RV_RUN(EBUS_RV_RUN),
        //thread-->rv_pc
        .THREAD_ID_FOR_PC_VALID(if_thread_id_valid),
        .THREAD_ID_FOR_PC(if_thread_id),
        //EX-->ISSUE
        .UPDATE_PC_THREAD_ID(ex_thread_id),
        .UPDATE_PC_VALID(update_pc_valid), 
        .UPDATE_PC(update_pc),
        //rv_pc-->imem
        .PC(if_pc)
    );
    
    //wait_para for 4 threads
    wire [4*32-1:0] all_wait_para;
    rv_thread  RV_THREAD(
        .CLK (CLK),
        .RST (RST),
        .EBUS_RV_RUN (EBUS_RV_RUN ),
        .INST (inst),
        .THREAD_ID_FOR_PC_VALID (if_thread_id_valid),
        .THREAD_ID_FOR_PC (if_thread_id),
        .ISSUE_THREAD_RUN (issue_thread_id_valid),
        .ISSUE_THREAD_ID (issue_thread_id),
        .SIGHARD ({15'h0}),
        .SIGSOFT (CSR_SIG_DOUT[15:0]),
        .ALL_WAIT_PARA  (all_wait_para)
    );
    
    //rs1 and rs2 from register file
    wire [31:0] regfile_rs1_dout;
    wire [31:0] regfile_rs2_dout;
    //wb_rd_value has the value to write rd register
    wire [31:0] wb_rd_value;
    rv_regfile RV_REGFILE (
      .CLK (CLK),
      .RST (RST),
      //ISSUE_THREAD_ID --> rv_regfile
      .RS_THREAD_VALID(decode_thread_id_valid),
      .RS_THREAD_ID (issue_thread_id),
      //Inst-->rv_regfile
      .RS1_INDEX (inst[19:15]),
      .RS2_INDEX (inst[24:20]),
      //WB-->rv_regfile
      .RD_THREAD_ID (wb_thread_id),
      .RD_INDEX (wb_rd_index),  //RD_INDEX==0 means NO regfile write
      .RD_DIN (wb_rd_value),
      //rv_regfile-->decoder
      .RS1_DOUT (regfile_rs1_dout),
      .RS2_DOUT  (regfile_rs2_dout)
    );
    
    //decoder-->ex
    wire [4:0] INST_TYPE;
    wire [2:0] FUNC3;
    wire [2:0] ALU_FUNC3;
    wire INST30;
    wire [4:0] RS1_INDEX;
    wire [4:0] RS2_INDEX;
    wire [31:0] DEC_RS1_VALUE;
    wire [31:0] DEC_RS2_VALUE;
    wire [31:0] IMM32;

    rv_decode rv_decode_dut (
      .CLK (CLK ),
      .RST (RST ),
      //IR --> decode
      .INST (ir),
      //ISSUE-->Decode
      .ISSUE_THREAD_ID (decode_thread_id),
      .ISSUE_PC (decode_pc),
      .WRITED_THREAD_ID(wb_thread_id),
      .RD_WRITED_INDEX(wb_rd_index),
      .RD_WRITED_VALUE(wb_rd_value),
      //Decode-->EX inst
      .INST_TYPE (INST_TYPE ),
      .FUNC3 (FUNC3 ),
      .ALU_FUNC3 (ALU_FUNC3 ),
      .INST30 (INST30 ),
      .RS1_INDEX (RS1_INDEX ),
      .RS2_INDEX (RS2_INDEX ),
      //Decode -->rd_index and rd_src chain
      .RD_INDEX (ex_rd_index),
      .RD_SRC(ex_rd_src),
      //Regfile --> decode
      .REGF_RS1_INDEX(ir[19:15]),
      .REGF_RS2_INDEX(ir[24:20]),
      .REGF_RS1_VALUE (regfile_rs1_dout),
      .REGF_RS2_VALUE (regfile_rs2_dout),
      //Decode-->EX Data
      .DEC_RS1_VALUE (DEC_RS1_VALUE ),
      .DEC_RS2_VALUE (DEC_RS2_VALUE ),
      .IMM32 (IMM32 )
    );

    //RS1 value forwarding
    wire [31:0] RS1_FORWARD;
    //RD Value for ALU and CSR Read instructions
    wire [31:0] EX_RD_VALUE;

    //EX --> ALL MEMORY MODULES
    wire [31:0] MEM_ADDR;
    wire [31:0] MEM_DIN;
    
    //EX --> DMEM
    wire DMEM_CS;

    //CSR --> EX
    wire [31:0] EX_CSR_DOUT;

    rv_ex rv_ex_dut (
      .CLK (CLK ),
      .RST (RST ),
      //Decode-->EX inst
      .INST_TYPE (INST_TYPE ),
      .FUNC3 (FUNC3 ),
      .ALU_FUNC3 (ALU_FUNC3 ),
      .INST30 (INST30 ),
      .RS1_INDEX (RS1_INDEX ),
      .RS2_INDEX (RS2_INDEX ),
      .RD_INDEX (ex_rd_index ),
      //Decode-->EX Data
      .RS1 (DEC_RS1_VALUE ),
      .RS2 (DEC_RS2_VALUE ),
      .IMM32 (IMM32 ),
      //PC chain-->EX
      .PC (ex_pc),

      //Decode-->EX Cur thread_id
      .THREAD_ID (ex_thread_id ),
      //MEM-->EX forwarding
      .MEM_THREAD_ID(mem_thread_id),
      .MEM_RD_INDEX(mem_rd_index),
      //WB-->EX forwarding
      .WB_THREAD_ID (wb_thread_id),
      .WB_RD_INDEX (wb_rd_index),
      .WB_RD_VALUE (wb_rd_value),
      //CSR -->EX
      .CSR_DOUT (EX_CSR_DOUT ),
      //Result of RS1 forwarding
      .RS1_FORWARD (RS1_FORWARD ),
      //EX-->MEM
      .EX_RD_VALUE (EX_RD_VALUE ),
      //EX --> ALL MEMORY MODULES
      .MEM_ADDR (MEM_ADDR ),
      .MEM_DIN (MEM_DIN ),
      .DMEM_CS (DMEM_CS ),
      //EX-->ISSUE
      .UPDATE_PC_VALID (update_pc_valid),
      .UPDATE_PC  (update_pc)
    );
    
    //CSR in EX stage
    //Signal for all CSR modules
    //CSR controller --> ALL CSR modules
    wire [11:0] CSR_ADDR;

    //CSR controller-->CSR_CYCLE
    wire CSR_CYCLE_CS;
    wire  [31:0] CSR_CYCLE_DOUT;

    //CSR controller-->CSR_SIG
    wire CSR_SIG_CS;
    wire  [31:0] CSR_SIG_DOUT;

    //CSR controller-->CSR_WAIT_PARA
    wire CSR_WAIT_PARA_CS;
    wire  [31:0] CSR_WAIT_PARA_DOUT;
    
    //CSR_THREAD_ID -->CSR Controller
    wire [31:0] CSR_THREAD_ID_DOUT;

    //CSR controller-->RV_FLAG
    wire CSR_RV_FLAG_CS;
    
    rv_csr rv_csr_dut (
      .CLK (CLK ),
      .RST (RST ),
      .INST_TYPE (INST_TYPE ),
      .FUNC3 (FUNC3 ),
      .RS1_INDEX (RS1_INDEX),
      .RD_INDEX (ex_rd_index ),
      .IMM32 (IMM32 ),
      .RS1_FORWARD (RS1_FORWARD),
      .CSR_ADDR (CSR_ADDR),
      .CSR_CYCLE_CS (CSR_CYCLE_CS),
      .CSR_CYCLE_DOUT (CSR_CYCLE_DOUT ),
      .CSR_SIG_CS (CSR_SIG_CS ),
      .CSR_SIG_DOUT (CSR_SIG_DOUT ),
      .CSR_WAIT_PARA_CS (CSR_WAIT_PARA_CS ),
      .CSR_WAIT_PARA_DOUT (CSR_WAIT_PARA_DOUT ),
      .CSR_RV_FLAG_CS (CSR_RV_FLAG_CS ),
      .CSR_THREAD_ID_DOUT (CSR_THREAD_ID_DOUT ),
      .CSR_DOUT  (EX_CSR_DOUT)
    );

    //MEM stage
    //DMEM
    wire [31:0] dmem_dout;
    rv_dmem  #(.addr_width (11)) rv_dmem_dut (
      .CLK (CLK ),
      .RST (RST ),
      .EBUS_SEL (EBUS_SEL ),
      .DMEM_CS (DMEM_CS ),
      .ADDR (MEM_ADDR),
      .INST_TYPE (INST_TYPE ),
      .FUNC3 (FUNC3 ),
      .DIN (MEM_DIN),
      .CS_EBUS (EBUS_DMEM_CS ),
      .WR_EBUS (EBUS_WR ),
      .ADDR_EBUS (EBUS_ADDR ),
      .DIN_EBUS (EBUS_DIN),
      .DOUT  (dmem_dout)
    );

    //mem_rd_value is the RD value for all stages
    wire [31:0] mem_rd_value;
    mux4w #(.WIDTH(32)) WB_RD_MUX(EX_RD_VALUE,dmem_dout,32'b0,32'b0,
      mem_rd_src,mem_rd_value);
    regw #(.WIDTH(32)) WB_RD_VALUE_REG(CLK,RST,1'b1,mem_rd_value,wb_rd_value);

    //CSR modules
    csr_cycle CSR_CYCLE_DUT(CLK,RST,CSR_ADDR,CSR_CYCLE_CS,CSR_CYCLE_DOUT);

    csr_thread_id CSR_THREAD_ID(ex_thread_id,CSR_THREAD_ID_DOUT);

    csr_rv_flag CSR_RV_FLAG_DUT(CLK,RST,FUNC3,RS1_INDEX,IMM32,RS1_FORWARD,
        CSR_RV_FLAG_CS,RV_FLAG);

    csr_thread_sig CSR_THREAD_SIG_DUT(CLK,RST,FUNC3,RS1_INDEX,ex_rd_index,
      IMM32,RS1_FORWARD,
      CSR_ADDR,CSR_SIG_CS,CSR_SIG_DOUT);

    csr_wait_para CSR_WAIT_PARA_DUT(CLK,RST,FUNC3,RS1_INDEX,ex_rd_index,
      IMM32,RS1_FORWARD,CSR_ADDR,
      CSR_WAIT_PARA_CS,CSR_WAIT_PARA_DOUT,ex_thread_id,all_wait_para);
endmodule